package com.ruoyi.exam.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.ruoyi.exam.domain.entity.exentity.ExamStatic;
import com.ruoyi.exam.domain.entity.Question;
import com.ruoyi.exam.mapper.QuestionMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.exam.domain.TPointsRules;
import com.ruoyi.exam.domain.entity.ExamPaper;
import com.ruoyi.exam.domain.entity.ExamPaperQuestion;
import com.ruoyi.exam.domain.entity.TTask;
import com.ruoyi.exam.domain.entity.TTaskExamPaperAnswer;
import com.ruoyi.exam.domain.entity.TTaskExe;
import com.ruoyi.exam.domain.entity.TWrongQuestion;
import com.ruoyi.exam.mapper.TPointsRulesMapper;
import com.ruoyi.exam.mapper.TTaskExamPaperAnswerMapper;
import com.ruoyi.exam.mapper.TTaskExeMapper;
import com.ruoyi.exam.mapper.TTaskMapper;
import com.ruoyi.exam.mapper.TWrongQuestionMapper;
import com.ruoyi.exam.service.ITTaskExamPaperAnswerService;

/**
 * 答题，记录用户的试卷答题情况Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-12-19
 */
@Service
public class TTaskExamPaperAnswerServiceImpl implements ITTaskExamPaperAnswerService {
    
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Autowired
    private TTaskExamPaperAnswerMapper tTaskExamPaperAnswerMapper;

    @Autowired
    private TTaskExeMapper tTaskExeMapper;

    @Autowired
    private TTaskMapper tTaskMapper;

    @Autowired
    private TWrongQuestionMapper tWrongQuestionMapper;

    @Autowired
    private TPointsRulesMapper tPointsRulesMapper;

    @Autowired
    private QuestionMapper questionMapper;

    /**
     * 查询答题，记录用户的试卷答题情况
     * 
     * @param id 答题，记录用户的试卷答题情况主键
     * @return 答题，记录用户的试卷答题情况
     */
    @Override
    public TTaskExamPaperAnswer selectTTaskExamPaperAnswerById(Long id) {
        return tTaskExamPaperAnswerMapper.selectTTaskExamPaperAnswerById(id);
    }

    /**
     * 查询答题，记录用户的试卷答题情况列表
     * 
     * @param tTaskExamPaperAnswer 答题，记录用户的试卷答题情况
     * @return 答题，记录用户的试卷答题情况
     */
    @Override
    public List<TTaskExamPaperAnswer> selectTTaskExamPaperAnswerList(TTaskExamPaperAnswer tTaskExamPaperAnswer) {
        return tTaskExamPaperAnswerMapper.selectTTaskExamPaperAnswerList(tTaskExamPaperAnswer);
    }

    /**
     * 新增答题，记录用户的试卷答题情况
     * 
     * @param tTaskExamPaperAnswer 答题，记录用户的试卷答题情况
     * @return 结果
     */
    @Override
    @Transactional
    public int insertTTaskExamPaperAnswer(TTaskExamPaperAnswer tTaskExamPaperAnswer) {
        // LoginUser loginUser = SecurityUtils.getLoginUser();
        tTaskExamPaperAnswer.setCreateTime(DateUtils.getNowDate());
        tTaskExamPaperAnswer.setUpdateTime(DateUtils.getNowDate());

        TTaskExe tTaskExe = tTaskExeMapper.selectTTaskExeById(tTaskExamPaperAnswer.gettTaskExeId());

        TTask tTask1 = tTaskMapper.selectTTaskById(tTaskExe.getTaskId());

        // 解析答卷内容，检查错题并记录
        String paperAnswerJson = tTaskExamPaperAnswer.getPaperAnswer();
        if (paperAnswerJson != null) {
            ExamPaper examPaper = JSON.parseObject(paperAnswerJson, ExamPaper.class);
            if (examPaper != null && examPaper.getExamPaperQuestions() != null) {
                Date now = DateUtils.getNowDate();

                // 遍历试卷中的每道题
                for (ExamPaperQuestion examPaperQuestion : examPaper.getExamPaperQuestions()) {
                    // 查询是否存在错题记录
                    TWrongQuestion queryWrong = new TWrongQuestion();
                    queryWrong.setUserId(tTaskExe.getUserId());
                    queryWrong.setQuestionId(examPaperQuestion.getId()); // 如果是每日一练类型，这里的Id是question的id，如果不是，则是exam_paper_question的id
                    List<TWrongQuestion> existingWrongs = tWrongQuestionMapper.selectTWrongQuestionList(queryWrong);

                    // 检查答案是否正确
                    if (!isAnswerCorrect(examPaperQuestion.getQuestionAnswer(), examPaperQuestion.getUserAnswer())) {
                        // 答错了，更新或创建错题记录
                        if (!existingWrongs.isEmpty()) {
                            // 更新已存在的错题记录
                            TWrongQuestion wrongQuestion = existingWrongs.get(0);
                            wrongQuestion.setWrongCount(wrongQuestion.getWrongCount() + 1);
                            wrongQuestion.setLastWrongTime(now);
                            wrongQuestion.setLastAnswer(examPaperQuestion.getUserAnswer());
                            wrongQuestion.setUpdateTime(now);
                            wrongQuestion.setUpdateBy(tTaskExamPaperAnswer.getUpdateBy());
                            wrongQuestion.setIsdaily(tTask1.getType() == 1?1:0);
                            tWrongQuestionMapper.updateTWrongQuestion(wrongQuestion);
                        } else {
                            // 创建新的错题记录
                            TWrongQuestion wrongQuestion = new TWrongQuestion();
                            wrongQuestion.setUserId(tTaskExe.getUserId());
                            wrongQuestion.setQuestionId(examPaperQuestion.getId());
                            wrongQuestion.setWrongCount(1L);
                            wrongQuestion.setLastWrongTime(now);
                            wrongQuestion.setLastAnswer(examPaperQuestion.getUserAnswer());
                            wrongQuestion.setCreateTime(now);
                            wrongQuestion.setUpdateTime(now);
                            wrongQuestion.setCreateBy(tTaskExamPaperAnswer.getCreateBy());
                            wrongQuestion.setUpdateBy(tTaskExamPaperAnswer.getUpdateBy());
                            wrongQuestion.setDeleted(0);
                            wrongQuestion.setIsdaily(tTask1.getType() == 1 ? 1 : 0);
                            tWrongQuestionMapper.insertTWrongQuestion(wrongQuestion);
                        }
                    } else if (!existingWrongs.isEmpty()) {
                        // 答对了，且存在错题记录，删除错题记录
                        Long[] wrongIds = existingWrongs.stream()
                                .map(TWrongQuestion::getId)
                                .toArray(Long[]::new);
                        tWrongQuestionMapper.deleteTWrongQuestionByIds(wrongIds);
                    }
                }
            }
        }

        // 更新任务执行状态
        if (tTaskExamPaperAnswer.gettTaskExeId() != null) {
            TTaskExe tTaskExeDb = tTaskExeMapper.selectTTaskExeById(tTaskExamPaperAnswer.gettTaskExeId());
            if (tTaskExeDb == null) {
                throw new RuntimeException("答卷未绑定任务，请联系管理员");
            }
            // 计算用户积分
            List<TPointsRules> tPointsRules = tPointsRulesMapper.selectTPointsRulesList(null);
            // 根据任务类型过滤出所需要的积分规则数据
            TTask tTask = tTaskMapper.selectTTaskById(tTaskExeDb.getTaskId());
            if (tTask == null) {
                throw new RuntimeException("任务不存在，请联系管理员");
            }
            List<TPointsRules> tPointsRulesList = tPointsRules.stream()
                    .filter(rule -> rule.getTaskType().equals(tTask.getType()))
                    .collect(Collectors.toList());

            // 计算用户积分
            for (TPointsRules rule : tPointsRulesList) {
                if (tTaskExamPaperAnswer.getUserScore() >= rule.getMinScore()
                        && tTaskExamPaperAnswer.getUserScore() <= rule.getMaxScore()) {
                    tTaskExamPaperAnswer.setPoints(rule.getPoints());
                }
            }

            // 保存答卷
            int row = tTaskExamPaperAnswerMapper.insertTTaskExamPaperAnswer(tTaskExamPaperAnswer);

            tTaskExeDb.setTaskStatus(1L); // 更新成已完成
            tTaskExeDb.setTaskExamPaperAnswerId(tTaskExamPaperAnswer.getId());
            tTaskExeMapper.updateTTaskExe(tTaskExeDb);

            return row;

        } else {
            throw new RuntimeException("答卷未绑定任务，请联系管理员");
        }
    }

    /**
     * 修改答题，记录用户的试卷答题情况
     * 
     * @param tTaskExamPaperAnswer 答题，记录用户的试卷答题情况
     * @return 结果
     */
    @Override
    public int updateTTaskExamPaperAnswer(TTaskExamPaperAnswer tTaskExamPaperAnswer) {
        tTaskExamPaperAnswer.setUpdateTime(DateUtils.getNowDate());
        return tTaskExamPaperAnswerMapper.updateTTaskExamPaperAnswer(tTaskExamPaperAnswer);
    }

    /**
     * 批量删除答题，记录用户的试卷答题情况
     * 
     * @param ids 需要删除的答题，记录用户的试卷答题情况主键
     * @return 结果
     */
    @Override
    public int deleteTTaskExamPaperAnswerByIds(Long[] ids) {
        return tTaskExamPaperAnswerMapper.deleteTTaskExamPaperAnswerByIds(ids);
    }

    /**
     * 删除答题，记录用户的试卷答题情况信息
     * 
     * @param id 答题，记录用户的试卷答题情况主键
     * @return 结果
     */
    @Override
    public int deleteTTaskExamPaperAnswerById(Long id) {
        return tTaskExamPaperAnswerMapper.deleteTTaskExamPaperAnswerById(id);
    }

    /**
     * 判断答案是否正确
     * 
     * @param correctAnswer 正确答案
     * @param userAnswer    用户答案
     * @return 是否正确
     */
    private boolean isAnswerCorrect(String correctAnswer, String userAnswer) {
        if (correctAnswer == null || userAnswer == null) {
            return false;
        }

        // 去除空格
        correctAnswer = correctAnswer.trim();
        userAnswer = userAnswer.trim();

        try {
            // userAnswer始终是数组格式
            List<String> userList = JSON.parseArray(userAnswer, String.class);
            if (userList == null || userList.isEmpty()) {
                return false;
            }

            // 如果是单选题或判断题，correctAnswer是普通字符串
            if (!correctAnswer.startsWith("[")) {
                // 单选题或判断题只会有一个答案
                return userList.size() == 1 && correctAnswer.equals(userList.get(0));
            }

            // 多选题，correctAnswer是数组格式
            try {
                // 将字符串转换为List进行比较
                List<String> correctList = JSON.parseArray(correctAnswer, String.class);

                if (correctList == null || userList == null || correctList.size() != userList.size()) {
                    return false;
                }

                // 排序后比较，确保顺序无关
                correctList.sort(String::compareTo);
                userList.sort(String::compareTo);

                return correctList.equals(userList);
            } catch (Exception e) {
                return false; // correctAnswer解析失败，返回false
            }
        } catch (Exception e) {
            // 发生任何异常都返回false
            return false;
        }
    }

    /**
     * 修复答题记录中的异常题目数据
     * 检测并修复paperAnswer中的空选项题目，自动填充正确答案并重新计分
     * 
     * @param id 答题记录主键
     * @return 修复的题目数量
     */
    @Override
    @Transactional
    public int fixAnswerData(Long id) {
        logger.info("开始修复答题记录ID: {}", id);
        
        // 1. 查询答题记录
        TTaskExamPaperAnswer answer = tTaskExamPaperAnswerMapper.selectTTaskExamPaperAnswerById(id);
        if (answer == null) {
            throw new RuntimeException("答题记录不存在");
        }
        
        if (StringUtils.isEmpty(answer.getPaperAnswer())) {
            logger.warn("答题记录没有答卷内容，无需修复");
            return 0;
        }
        
        try {
            // 调用内部修复方法
            int fixedCount = fixSingleAnswerData(answer);
            
            if (fixedCount > 0) {
                logger.info("修复完成，修复了{}道题目", fixedCount);
            } else {
                logger.info("未发现需要修复的题目");
            }
            
            return fixedCount;
            
        } catch (Exception e) {
            logger.error("修复答题记录时发生异常：{}", e.getMessage(), e);
            throw new RuntimeException("修复失败：" + e.getMessage());
        }
    }
    
    /**
     * 规范化题目标题，去除多余空格和特殊字符
     */
    private String normalizeQuestionTitle(String title) {
        if (StringUtils.isEmpty(title)) {
            return title;
        }
        return title.trim().replaceAll("\\s+", " ");
    }
    
    /**
     * 通过题目标题查找正确的题目
     */
    private Question findCorrectQuestion(String normalizedTitle) {
        try {
            // 精确匹配
            Question queryParam = new Question();
            queryParam.setQuestionTitle(normalizedTitle);
            List<Question> questions = questionMapper.selectQuestionList(queryParam);
            
            if (!questions.isEmpty()) {
                return questions.get(0);
            }
            
            // 模糊匹配：查询所有题目进行内存比较
            List<Question> allQuestions = questionMapper.selectQuestionList(new Question());
            return allQuestions.stream()
                .filter(q -> {
                    String dbTitle = normalizeQuestionTitle(q.getQuestionTitle());
                    return normalizedTitle.equals(dbTitle);
                })
                .findFirst()
                .orElse(null);
                
        } catch (Exception e) {
            logger.error("查找题目时发生异常：{}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 重新计算分数和正确题数
     */
    private void recalculateScore(ExamPaper examPaper, TTaskExamPaperAnswer answer) {
        long correctCount = 0;
        float totalScore = 0f;
        
        for (ExamPaperQuestion question : examPaper.getExamPaperQuestions()) {
            if (isAnswerCorrect(question.getQuestionAnswer(), question.getUserAnswer())) {
                correctCount++;
                totalScore += question.getQuestionScore() != null ? question.getQuestionScore().floatValue() : 0;
            }
        }
        
        answer.setQuestionCorrect(correctCount);
        answer.setUserScore(totalScore);
        
        logger.info("重新计算分数完成，正确题数：{}，总分：{}", correctCount, totalScore);
    }

    /**
     * 批量修复所有答题记录中的异常题目数据
     * 检测并修复所有paperAnswer中的空选项题目，自动填充正确答案并重新计分
     * 
     * @return 修复的题目总数量
     */
    @Override
    @Transactional
    public int fixAllAnswerData() {
        logger.info("开始批量修复所有答题记录");
        
        // 1. 查询所有答题记录
        TTaskExamPaperAnswer queryParam = new TTaskExamPaperAnswer();
        queryParam.setDeleted(0); // 只查询未删除的记录
        List<TTaskExamPaperAnswer> allAnswers = tTaskExamPaperAnswerMapper.selectTTaskExamPaperAnswerList(queryParam);
        
        if (allAnswers.isEmpty()) {
            logger.warn("没有找到答题记录，无需修复");
            return 0;
        }
        
        int totalFixedCount = 0;
        int processedCount = 0;
        int errorCount = 0;
        
        logger.info("找到{}条答题记录，开始逐条修复", allAnswers.size());
        
        // 2. 逐条处理每个答题记录
        for (TTaskExamPaperAnswer answer : allAnswers) {
            try {
                processedCount++;
                
                if (StringUtils.isEmpty(answer.getPaperAnswer())) {
                    logger.debug("答题记录ID:{} 没有答卷内容，跳过", answer.getId());
                    continue;
                }
                
                // 调用单条修复逻辑
                int fixedCount = fixSingleAnswerData(answer);
                totalFixedCount += fixedCount;
                
                if (fixedCount > 0) {
                    logger.info("答题记录ID:{} 修复了{}道题目", answer.getId(), fixedCount);
                }
                
                // 每处理100条记录输出一次进度日志
                if (processedCount % 100 == 0) {
                    logger.info("批量修复进度: {}/{}, 已修复题目总数: {}", processedCount, allAnswers.size(), totalFixedCount);
                }
                
            } catch (Exception e) {
                errorCount++;
                logger.error("修复答题记录ID:{} 时发生异常: {}", answer.getId(), e.getMessage(), e);
                // 继续处理下一条记录，不中断整个批量处理
            }
        }
        
        logger.info("批量修复完成！处理记录数: {}, 修复题目总数: {}, 错误数: {}", 
                   processedCount, totalFixedCount, errorCount);
        
        return totalFixedCount;
    }
    
    /**
     * 修复单条答题记录的内部方法
     * 从fixAnswerData方法中提取出来，避免重复代码
     */
    private int fixSingleAnswerData(TTaskExamPaperAnswer answer) {
        try {
            // 解析答卷内容
            ExamPaper examPaper = JSON.parseObject(answer.getPaperAnswer(), ExamPaper.class);
            if (examPaper == null || examPaper.getExamPaperQuestions() == null || examPaper.getExamPaperQuestions().isEmpty()) {
                return 0;
            }
            
            int fixedCount = 0;
            
            // 遍历题目进行修复
            for (ExamPaperQuestion question : examPaper.getExamPaperQuestions()) {
                String questionText = question.getQuestionText();
                String questionTitle = question.getQuestionTitle();
                
                // 检查是否为空选项数据
                if (StringUtils.isEmpty(questionText) || "[]".equals(questionText) || "\"\"".equals(questionText)) {
                    
                    // 通过题目标题查询正确的选项数据
                    String normalizedTitle = normalizeQuestionTitle(questionTitle);
                    Question correctQuestion = findCorrectQuestion(normalizedTitle);
                    
                    if (correctQuestion != null && StringUtils.isNotEmpty(correctQuestion.getQuestionText()) && 
                        !"[]".equals(correctQuestion.getQuestionText())) {
                        
                        // 修复题目选项
                        question.setQuestionText(correctQuestion.getQuestionText());
                        
                        // 自动填充正确答案，统一转换为数组格式
                        String correctAnswer = correctQuestion.getQuestionAnswer();
                        String userAnswerArray = convertToArrayFormat(correctAnswer);
                        question.setUserAnswer(userAnswerArray);
                        
                        fixedCount++;
                    }
                }
            }
            
            if (fixedCount > 0) {
                // 重新计算分数和正确题数
                recalculateScore(examPaper, answer);
                
                // 更新数据库
                answer.setPaperAnswer(JSON.toJSONString(examPaper));
                answer.setUpdateTime(DateUtils.getNowDate());
                tTaskExamPaperAnswerMapper.updateTTaskExamPaperAnswer(answer);
            }
            
            return fixedCount;
            
        } catch (Exception e) {
            logger.error("修复单条答题记录时发生异常：{}", e.getMessage(), e);
            throw e; // 重新抛出异常，让调用方处理
        }
    }
    
    /**
     * 将答案转换为统一的数组格式
     * 单选题答案 "A" -> ["A"]
     * 多选题答案 ["A","B","C"] -> ["A","B","C"]
     */
    private String convertToArrayFormat(String answer) {
        if (StringUtils.isEmpty(answer)) {
            return "[]";
        }
        
        answer = answer.trim();
        
        // 如果已经是数组格式，直接返回
        if (answer.startsWith("[") && answer.endsWith("]")) {
            return answer;
        }
        
        // 单选题答案，转换为数组格式
        try {
            // 使用JSON格式包装单个答案
            return JSON.toJSONString(new String[]{answer});
        } catch (Exception e) {
            logger.error("转换答案格式时发生异常：{}", e.getMessage(), e);
            return JSON.toJSONString(new String[]{answer});
        }
    }
}
